//权限控制
//路由守卫代码

//导入路由实例
import router, { anyncRoutes } from "./router"; //{}这是按需导入，不加{}是默认导入
//导入store实例
import store from "./store";
// 导入nprogress模块（进入页面加载提示）
import NProgress from "nprogress";
// 导入nprogress的样式
import "nprogress/nprogress.css";

//白名单数组，这里放的是无需进行登录就可以访问该路由路径
const whiteList = ["/login", "/404"];

//注册全局前置守卫(就是先拿到用户的信息在进行跳转)
// to是去到的路由对象
router.beforeEach(async (to, from, next) => {
  //开启进度条的加载提示
  NProgress.start();
  //从vuex中获取token （加上{}就是进行解构） 判断当前用户是否有值
  const { token } = store.state.user; // 这是进行解构
  // const {token}=store.state.user.token  这是不是进行解构的操作
  //判断
  if (token) {
    //登录了
    // 如果要去路由路径在白名单中
    // 如果还要登录（这个实现404的跳转，要是输入没有的路由会进行跳转）
    if (to.path === "/login") {
      // 没必要去了，去首页
      next("/"); //这是默认的路径是layout
      //关闭进度条的加载提示
      NProgress.done();
    } else {
      //获取用户信息action在这里调用(在展示内容之前我们要展示，所以在此调用)
      // 注意：
      // 1.此项目的核心在权限控制，就是不同员工登录进来看到的主页菜单不同
      // 2.如果员工登录成功了，已经跳转至主页在发送请求，获取员工的角色权限已经太晚了
      // 3.这个获取员工的角色权限信息的时机是在跳转至主页之前，拿到当前员工的角色信息，知道你是谁了
      //  有哪些权限，然后在对应的开放左侧菜单，这些操作都做完了，在让员工跳转至主页，这个时候ta所
      //  看到的左侧菜单就是ta具备的权限
      // 4.只是现在还不知道如何开放现在对应的左侧菜单，这个点先进行预留，大概原理就是根据员工的角色列表信息
      // 动态筛选动态路由表即可实现？？？

      //这个地方代码当路由切换的时候会多次执行，会发起多次取消请求，需要利用判断来进行优化代码
      //如果没有用户信息，才发起请求，有了用户信息就不发送请求
      // 第1种解决方式：判断vuex中的userId有没有
      if (!store.state.user.userInfo.userId) {
        //这是拿的userinfo的id值
        // await关键字的目的是等待action函数执行完毕，才继续往后执行（异步变同步）
        await store.dispatch("user/getUserInfoAction"); //用直接的方式触发
        // 获取当前用户的menus（他就是分配的权限）数组
        const { menus } = store.state.user.userInfo.roles;
        // 基于当前用户信息中 roles.menus 数组来筛选动态路由表

        // 触发route/filterAsyncRouteAction这个函数,拿到筛选后的动态路由表
        const showAsyncRoutes = await store.dispatch(
          "route/filterAsyncRouteAction",
          menus
        );
        // 这是打印的在这个页面所 展示的路由信息数组
        console.log("showAsyncRoutes", showAsyncRoutes);
        // 把筛选的结果在动态追加到路由表中 rotter.addRoutes（已废弃）
        //rotter.addRoutes(路由对象数组)：同时追加多个路由规则到路由表中
        //rotter.addRoute(路由对象数组)：同时追加1个路由规则到路由表中
        //把筛选的动态路由结果加入到路由表中，这样今后输入path，才能访问到compoennt
        //否则就算知道路由path，访问仍然会404
        //*********************************** */
        router.addRoutes([
          ...showAsyncRoutes,
          { path: "*", redirect: "/404", hidden: true },
        ]);
        //刷新一下路由表，重新进一次
        return next({
          ...to, //保留原有所有要去的路由信息(可以理解为重进一次)
          replace: true, // 替换刚才那一次跳转的历史记录
        });
      }
      // 这69-78的代码，负责输入路由path。能看到对应组件的内容
      /********************************************* */
      // ****************************************
      //这里拿到了用户信息，用户信息里有个 userInfo.roles,menus
      //  可以拿到当前员工的角色列表这个角色列表数组中的字符串表明了
      // 当前员工可以看到的左侧菜单，今后基于这个数组对动态路由表做筛选，
      // 然后在调至首页，这样首页展示的左侧菜单就是当前员工能看到的

      // 第2种解决方式：拿到action函数的返回值
      // 注意：所有的action函数返回值都是Promise实例，要接收action函数的返回值，需要配合await关键字
      // const userObj = await store.dispatch('user/getUserInfoAction')
      // 判断userObj中是否存在userId，如果没有再发请求
      // 否则放行
      next();
    }
  } else {
    //未登录
    // 进一步判断，要去的路由路径是否在白名单中
    if (whiteList.includes(to.path)) {
      // 如果在
      // 放行
      next();
    } else {
      //否则
      //跳转至登录，并携带回跳地址l
      next(`/login?redirectUrl=${to.path}`);
      //关闭进度条的加载提示
      NProgress.done();
    }
  }
});

// 注册全局后置守卫（路由跳转之后会触发）
router.afterEach(() => {
  //关闭进度条的加载提示done
  NProgress.done();
});

// 按钮的操作权控制:
// 1.移除或显示（v-if=“条件”）
// 2.禁用（：display=“！条件”）
// 3.显示，也不禁用，给出无权操作的提示
// 有三种方式
